package com.ibp.service.impl;

import com.ibp.comparator.ComparatorHM;
import com.ibp.comparator.ComparatorSN;
import com.ibp.entity.HostMachine;
import com.ibp.entity.ServiceNode;
import com.ibp.entity.ServiceStatusEnum;
import com.ibp.entity.SysRunManage;
import com.ibp.service.DictDataService;
import com.ibp.service.FSHttpService;
import com.ibp.service.ServiceNodeService;
import com.ibp.service.SysRunManageService;
import com.ibp.utils.SocketClientUtils;
import com.ibp.utils.StringUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("serviceNodeServiceImpl")
public class ServiceNodeServiceImpl implements ServiceNodeService,InitializingBean{

  private static Logger logger = LoggerFactory.getLogger(ServiceNodeServiceImpl.class);

  private String ibms_ip = null;
  private String ibms_port = null;
  private String ibms_nodes = null;
  private String url = null;
  
  private ServletContext servletContext;  
  
  @Autowired
  FSHttpService fSHttpServiceImpl;
  @Autowired
  SysRunManageService sysRunManageServiceImpl;
  @Autowired
  DictDataService dictDataServiceImpl;

  /***
   * 返回服务节点列表
   */
  @SuppressWarnings("unchecked")
public List<ServiceNode> getServiceNodes(ServiceNode sn)
  {
    List<ServiceNode> nodes = new ArrayList<ServiceNode>();
    List<SysRunManage> ibas = this.sysRunManageServiceImpl.getSessions("ibas");
    List<SysRunManage> ibma = this.sysRunManageServiceImpl.getSessions("ibma");
    String response = this.fSHttpServiceImpl.sendPostRequest(this.url);
    if (!StringUtil.isEmpty(response)) {
      nodes = parseResponse(response);
      Collections.sort(nodes,new ComparatorSN());
    }
    List<ServiceNode> list = mergeData(nodes, ibas,ibma);
    //过滤
    filter(list,sn);
    return list;
  }


  /***
   * 过滤结果集
   * @param list
   * @param sn
   * @return
   */
  public List<ServiceNode> filter(List<ServiceNode> list, ServiceNode sn){
	 
	  if(sn != null){
		 String regex_sn = String2Regex(sn.getServiceNodeSearch());
		 String regex_hm = String2Regex(sn.getHostMachineAddressSearch());
		 for(Iterator<ServiceNode> it=list.iterator();it.hasNext();){
			 ServiceNode s = it.next();
			 if((StringUtil.isEmpty(regex_sn) ? true : (StringUtil.isEmpty(s.getServiceNodeSearch()) ? false : s.getServiceNodeSearch().matches(regex_sn)))
				&& (StringUtil.isEmpty(regex_hm) ? true : (StringUtil.isEmpty(s.getHostMachineAddressSearch()) ? false : s.getHostMachineAddressSearch().matches(regex_hm))) ){
				 continue ;
			 }else{
				 it.remove();
			 }
		 } 
	  }
	  return list ;
  }
  
  /***
   * 根据输入的查询条件生成正则表达式
   * '*' -- 表示匹配任意字符
   * '?' --匹配一个字符 
   * @param str
   * @return
   */
  protected String String2Regex(String str) {
	  if(StringUtil.isEmpty(str)){
		  return null ;
	  }
	  return str.replaceAll("\\.", "\\.")
				  .replaceAll("\\*", ".*")
				  .replaceAll("\\?", ".{1}")
				  .replaceAll("\\(", "\\\\(")
				  .replaceAll("\\)", "\\\\)");
	}
  
  
  /***
   * 合并节点会话数据
   * @param nodes
   * @param ibases
   * @return
   * 
   * 	ibms -s nodes得到所有没有颜色的信息
		ibms -s sessions
			ibas行有
				关联ibma行是否存在
					设置"A"绿色
				不存在
					设置"A"红色
				设置"(B)"绿色
			ibas行没有
				连接ibcmd成功
					发送远程命令ibma.sh status判断ibma是否启动，设置"A"绿色或红色
					发送远程命令ibas.sh status判断ibas是否启动，设置"(B)"黄色或红色
				连接失败
					设置"A(B)"设置成黄色
   */
  @SuppressWarnings("unchecked")
protected List<ServiceNode> mergeData(List<ServiceNode> nodes, List<SysRunManage> ibases,List<SysRunManage> ibmas){

	  //遍历所有服务节点

	  for (ServiceNode sn : nodes) {
	      //节点名
		  String node = sn.getServiceNode();
	      //主机地址
	      List<HostMachine> hostMachines = sn.getHostMachines();
	      //排序（根据主机名IP排序）
	      Collections.sort(hostMachines,new ComparatorHM());
	      //页面显示 的主机地址拼接字符串（含HTML元素）
	      StringBuilder addressString =  new StringBuilder();
	      //作为过滤查询的主机地址拼接字符串（不含HTML元素）
	      StringBuilder addressSearch =  new StringBuilder();
	      //启停按钮
	  	  String ibma_stop =  "<button id=\"b_stop\" type=\"button\" class=\"btn btn-mini btn-success \"  onclick=\"executeIbcmd($(this),'ibma.sh stop \\n')\">停</button>";
	  	  String ibma_start = "<button id=\"b_start\" type=\"button\" class=\"btn btn-mini btn-danger\"   onclick=\"executeIbcmd($(this),'ibma.sh start \\n')\">启</button>";
	  	  String ibas_stop =  "<button id=\"b_stop\" type=\"button\" class=\"btn btn-mini btn-success \"  onclick=\"executeIbcmd($(this),'ibas.sh stop \\n')\">停</button>";
	  	  String ibas_start = "<button id=\"b_start\" type=\"button\" class=\"btn btn-mini btn-danger\"   onclick=\"executeIbcmd($(this),'ibas.sh start \\n')\">启</button>";
	      String ib_warning = "<button id=\"b_warning\" type=\"button\" class=\"btn btn-mini btn-warning\"   disabled=\"true\"> </button>";
	  	  //循环遍历主机地址
	      for (HostMachine hm : hostMachines) {
	    	    String address = hm.getIbasAddress() ;
	    	    //主机地址
		    	String hostMachineAddress = null ;
			    //主机地址（过滤字段）
		    	String hostMachineAddressSearch = null ; //作为主机地址的过滤字段	      	
	            //存在对应的ibas则为true
	      		boolean ibasFlag = false ;
		    	//关联地址
	      		String joinAddress = null ;
	      		//遍历ibas(通讯服务端会话)，判断主机启停状态
		    	for (SysRunManage ibas : ibases) {
		    		hostMachineAddressSearch = address;
		    		//判断节点名和主机地址
		      		if (node.equals(ibas.getSessionNode()) && address.equals(ibas.getRemoteAdress())) {
		          	  ibasFlag = true ;
		          	  joinAddress = ibas.getIbmaLocalAddress();
		          	  //设置"(B)"绿色
		          	  hostMachineAddress = setColor(address,"#33cc00")+ibas_stop;
		          	  hm.setIbasStatus(ServiceStatusEnum.START);
		          	  break;
		            }
		        }
		      	/***
						ibas行有
							关联ibma行是否存在
								设置"A"绿色
							不存在
								设置"A"红色
							设置"(B)"绿色
						ibas行没有
							连接ibcmd成功
								发送远程命令ibma.sh status判断ibma是否启动，设置"A"绿色或红色
								发送远程命令ibas.sh status判断ibas是否启动，设置"(B)"黄色或红色
							连接失败
								设置"A(B)"设置成黄色
		      	 */
		    	//注册代理地址
		        String ibmaAddress = null ;
		        //注册代理（过滤字段）
		        String ibmaAddressSearch = null ;
		    	if(ibasFlag){  //ibas行有
		    		//关联ibma行是否存在
		    		boolean ibmaFlag = false ;
		    		//遍历注册代理地址，判断代理启停状态
		            for(SysRunManage ibma:ibmas){
		            	if(node.equals(ibma.getSessionNode()) && joinAddress.equals(ibma.getLocalAdress())){
		            		ibmaFlag =  true ;
		            		ibmaAddress = setColor(returnIp(address),"#33cc00")+ibma_stop ;
		            		ibmaAddressSearch = returnIp(address) ;
		            		hm.setIbmaStatus(ServiceStatusEnum.START);
		            		break;
		            	}
		            }
		            //关联ibma行不存在
		            if(!ibmaFlag){
		            	ibmaAddress = setColor(returnIp(address),"red")+ibma_start;
		            	ibmaAddressSearch = returnIp(address) ;
		            	hm.setIbmaStatus(ServiceStatusEnum.STOP);
		            }else{

		            }
		      	}else{  //ibas行没有
		      		//String socketIp = returnIp(address) ;
		      		String socketIp = "172.16.68.110" ;
		      		String socketPort = getCmdPort(address);
		      		//连接ibcmd成功
		      		if(SocketClientUtils.socketConnectStatus(socketIp, socketPort)){
		    			//发送远程命令ibma.sh status判断ibma是否启动，设置"A"绿色或红色
		      			if(SocketClientUtils.sendexecuteCmd(socketIp, socketPort, "ibma.sh status \n")){
		      				  ibmaAddress = setColor(returnIp(address),"#33cc00")+ibma_stop ;
		      				  ibmaAddressSearch = returnIp(address) ;
		      				  hm.setIbmaStatus(ServiceStatusEnum.START);
		      			 }else{
		      				  ibmaAddress = setColor(returnIp(address),"red")+ibma_start;
		      				  ibmaAddressSearch = returnIp(address) ;
		      				  hm.setIbmaStatus(ServiceStatusEnum.STOP);
		      			 }
		      			
		      			 //发送远程命令ibas.sh status判断ibas是否启动，设置"(B)"黄色或红色
		      			 if(SocketClientUtils.sendexecuteCmd(socketIp, socketPort, "ibas.sh status \n")){
				          	  hostMachineAddress = setColor(address,"#33cc00")+ibas_stop;
				          	  hostMachineAddressSearch = address;
				          	  hm.setIbasStatus(ServiceStatusEnum.START);
		      			 }else{
				          	  hostMachineAddress = adjustPort(address,ibas_start);
				          	  hostMachineAddressSearch = adjustPortSearch(address);
				          	  hm.setIbasStatus(ServiceStatusEnum.STOP);
		      			 }
		      		}else{  //连接失败,设置"A(B)"设置成黄色
		      			
			          	  hostMachineAddress = setColor(address,"#faa732")+ib_warning;
			          	  hostMachineAddressSearch = address;
			          	  hm.setIbasStatus(ServiceStatusEnum.UNKNOWN);
			          	  
	      				  ibmaAddress = setColor(returnIp(address),"#faa732")+ib_warning ;
	      				  ibmaAddressSearch = returnIp(address) ;
	      				  hm.setIbmaStatus(ServiceStatusEnum.UNKNOWN);
	      				  
		      		}
		      	}
		    	//判断ibas主机服务是否存在，如果不存在将ibas状态设为NULL(无服务)
		    	if(adjustPort(address)){
		    		hm.setIbasStatus(ServiceStatusEnum.NULL);
		    	}
		    	hostMachineAddress = StringUtil.isEmpty(hostMachineAddress) ? "" : "("+ hostMachineAddress +")";
		    	hostMachineAddressSearch = StringUtil.isEmpty(hostMachineAddressSearch) ? "" : "("+ hostMachineAddressSearch +")" ;
		    	//拼接代理服务地址和主机地址
		    	addressString.append("     ");
		    	addressString.append("<span ip=\""+ this.returnIp(address) + "\" port=\""+ getCmdPort(address) +"\"><span>"+ibmaAddress+"</span><span>"+hostMachineAddress+"</span></span>&nbsp;&nbsp;&nbsp;&nbsp;");
		    	addressSearch.append("     ");
		    	addressSearch.append(ibmaAddressSearch+hostMachineAddressSearch);
		    	
	      }
	      sn.setHostMachineAddressString(addressString.toString());
	      sn.setHostMachineAddressSearch(addressSearch.toString());
	      
	      /*** 设置节点的显示颜色和启停按钮切换  ***/
	      //节点状态
	      ServiceStatusEnum nodeStatus = sn.getServiceNodeStatus();
	      ServiceStatusEnum nodeIbmaStatus = sn.getServiceNodeIbmaStatus();
	      ServiceStatusEnum nodeIbasStatus = sn.getServiceNodeIbasStatus();
	      //启停按钮
	  	  String node_ibma_stop =   "<button id=\"b_stop\" type=\"button\" class=\"btn btn-mini btn-success \"  onclick=\"executeIbmsCmd($(this),'ibma_cluster.sh "+ node +" stop \\n')\">停</button>";
	  	  String node_ibma_start =  "<button id=\"b_start\" type=\"button\" class=\"btn btn-mini btn-danger\"   onclick=\"executeIbmsCmd($(this),'ibma_cluster.sh "+ node +" start \\n')\">启</button>";
	  	  String node_ibma_unknow_stop = "<button id=\"b_start\" type=\"button\" class=\"btn btn-mini btn-warning\"  onclick=\"executeIbmsCmd($(this),'ibma_cluster.sh "+ node +" stop \\n')\">停</button>";
	  	  String node_ibma_unknow_start = "<button id=\"b_start\" type=\"button\" class=\"btn btn-mini btn-warning\"  onclick=\"executeIbmsCmd($(this),'ibma_cluster.sh "+ node +" start \\n')\">启</button>";
	  	  
	  	  String node_ibas_stop =   "<button id=\"b_stop\" type=\"button\" class=\"btn btn-mini btn-success \"  onclick=\"executeIbmsCmd($(this),'ibas_cluster.sh "+ node +" stop \\n')\">停</button>";
	  	  String node_ibas_start =  "<button id=\"b_start\" type=\"button\" class=\"btn btn-mini btn-danger\"   onclick=\"executeIbmsCmd($(this),'ibas_cluster.sh "+ node +" start \\n')\">启</button>";
	  	  String node_ibas_unknow_stop = "<button id=\"b_start\" type=\"button\" class=\"btn btn-mini btn-warning\"  onclick=\"executeIbmsCmd($(this),'ibas_cluster.sh "+ node +" stop \\n')\">停</button>";
	  	  String node_ibas_unknow_start = "<button id=\"b_start\" type=\"button\" class=\"btn btn-mini btn-warning\"  onclick=\"executeIbmsCmd($(this),'ibas_cluster.sh "+ node +" start \\n')\">启</button>";
	  	  
	  	  if(nodeIbmaStatus.equals(ServiceStatusEnum.START) && nodeIbasStatus.equals(ServiceStatusEnum.START) ){
	    	  //绿色(ibma全部正常启动，ibas全部正常启动)
	    	  sn.setServiceNode(setColor(node,"#33cc00")+" "+node_ibma_stop+" "+node_ibas_stop);
	    	  
	      }else if(nodeIbmaStatus.equals(ServiceStatusEnum.START) && nodeIbasStatus.equals(ServiceStatusEnum.NULL) ){
	    	  //绿色(ibma全部正常启动，无ibas服务)
	    	  sn.setServiceNode(setColor(node,"#33cc00")+" "+node_ibma_stop);
	    	  
	      }else if(nodeIbmaStatus.equals(ServiceStatusEnum.STOP) && nodeIbasStatus.equals(ServiceStatusEnum.STOP) ){
	    	  //红色(ibma全部停止，ibas全部停止)
	    	  sn.setServiceNode(setColor(node,"red")+" "+node_ibma_start+" "+node_ibas_start);
	    	  
	      }else if(nodeIbmaStatus.equals(ServiceStatusEnum.STOP) && nodeIbasStatus.equals(ServiceStatusEnum.NULL) ){
	    	  //红色(ibma全部停止，无ibas服务)
	    	  sn.setServiceNode(setColor(node,"red")+" "+node_ibma_start);
	    	  
	      }else{
	    	  //黄色
	    	  StringBuilder nodeSb = new StringBuilder(setColor(node,"#faa732"));
	    	  //设置ibma启停按钮
	    	  if(nodeIbmaStatus.equals(ServiceStatusEnum.START)){
	    		  nodeSb.append(" ");
	    		  nodeSb.append(node_ibma_stop);
	    	  }else if(nodeIbmaStatus.equals(ServiceStatusEnum.STOP)){
	    		  nodeSb.append(" ");
	    		  nodeSb.append(node_ibma_start);
	    	  }else{
	    		  nodeSb.append(" ");
	    		  nodeSb.append(node_ibma_unknow_stop);
	    	  }
	    	  //设置ibas启停按钮
	    	  if(nodeIbasStatus.equals(ServiceStatusEnum.START)){
	    		  nodeSb.append(" ");
	    		  nodeSb.append(node_ibas_stop);
	    	  }else if(nodeIbasStatus.equals(ServiceStatusEnum.STOP)){
	    		  nodeSb.append(" ");
	    		  nodeSb.append(node_ibas_start);
	    	  }else if(nodeIbasStatus.equals(ServiceStatusEnum.NULL)){
	    		  
	    	  }else if(nodeIbasStatus.equals(ServiceStatusEnum.NULL_STOP)){
	    		  nodeSb.append(" ");
	    		  nodeSb.append(node_ibas_unknow_start);
	    	  }else{
	    		  nodeSb.append(" ");
	    		  nodeSb.append(node_ibas_unknow_stop);
	    	  }
	    	  sn.setServiceNode(nodeSb.toString());
	      }
	  	  
	  }

	  return nodes;

  }

  //获取cmd端口号,将端口号的第一个数字1替换成2;如果第一个数字不为1，则端口获取异常
  protected String getCmdPort(String address){
	  String port =  returnPort(address) ;
	  if(port != null){
		  port = port.replaceAll("[-|)]", "").replaceFirst("1", "2");
		  return port ;
	  }
	  return "" ;
  }
  //设置显示颜色
  protected String setColor(String str, String color) {
    return "<font color='" + color + "'>" + str + "</font>";
  }

  //截取IP
  protected String returnIp(String address){
	  if(address != null){
		  int index = address.indexOf(":") ;
		  return address.substring(0, index>-1 ? index : address.length()-1);
	  }
	  return null ;
  }
  //截取端口号
  protected String returnPort(String address){
	  if(address != null){
		  int index = address.indexOf(":") ; 
		  return address.substring(index+1, address.length());
	  }
	  return null ;
  }
  
  //判断端口号是否为负数
  protected boolean adjustPort(String address){
	  if(!StringUtil.isEmpty(address)){
		  String port = returnPort(address);
		  if(Integer.valueOf(port)<0){
			 return true ;
		  }else{
			 return false;
		  }
	  }
	  return false ;
  }
  
  //判断端口号是否为负数，显示地址的样式
  protected String adjustPort(String address,String button){
	  if(!StringUtil.isEmpty(address)){
		  String port = returnPort(address);
		  if(Integer.valueOf(port)<0){
			 return "" ;
			  // return "<span style=\"display:none;\">"+setColor(address,"red")+button+"</span>" ;
		  }else{
			  return setColor(address,"red")+button;
		  }
	  }
	  return "" ;
  }
  
  protected String adjustPortSearch(String addressSearch){
	  if(!StringUtil.isEmpty(addressSearch)){
		  String port = returnPort(addressSearch);
		  if(Integer.valueOf(port)<0){
			  return "" ;
		  }else{
			  return addressSearch;
		  }
	  }
	  return "" ;
  }
  
  /***
   * 解析返回的响应字符串
   * @param response
   * @return
   */
protected List<ServiceNode> parseResponse(String response){
    List<ServiceNode> list = new ArrayList<ServiceNode>();
    String[] str = response.split("[\n]+");
    for (int i = 0; i < str.length; ++i) {
      String[] s = str[i].split("[ ]+");
      ServiceNode sn = new ServiceNode();
      for (int j = 0; j < s.length; ++j) {
        sn.setServiceNode(s[0]);
        sn.setServiceNodeSearch(s[0]);
        if (s.length > 2) {
          List<HostMachine> l = new ArrayList<HostMachine>();
          for (int k = 2; k < s.length; ++k) {
        	  HostMachine hm = new HostMachine() ;
        	  hm.setIbasAddress(hostMachineAddressSub(s[k]));
        	  l.add(hm);
          }
          sn.setHostMachines(l);
          sn.setHostMachineAddressString(l.toString());
        }
      }
      list.add(sn);
    }
    return list;
  }

  
  protected String hostMachineAddressSub(String HostMachineAddress){
    if ((HostMachineAddress != null) && (!"".equals(HostMachineAddress))) {
      int index = HostMachineAddress.indexOf("(");
      return HostMachineAddress.substring(0, index);
    }
    return null;
  }

  
  @SuppressWarnings("unchecked")
	public void afterPropertiesSet() throws Exception {
	  	this.servletContext = dictDataServiceImpl.getServletContext();
	  	logger.info("初始化服务节点ip和port配置,servletContext:"+servletContext); 
	    Map<String,Map<String,String>> dictMap = (Map<String, Map<String, String>>) this.servletContext.getAttribute("dictMap");
	    
	    this.ibms_ip = 	  dictMap.get("http.ibms").get("ip");
	    this.ibms_port =  dictMap.get("http.ibms").get("port");
	    this.ibms_nodes = dictMap.get("http.ibms").get("nodes");
	    this.url = ("http://" + this.ibms_ip + ":" + this.ibms_port + "/" + this.ibms_nodes);
	  }



}